
To be able to make auditing as flexible as possible, the recorder is notified with as much changes as possible, so the developer can make the right decision what to record as audit information and what to ignore.
The following changes and actions are recognized to be useful auditing information.
Action 7 and 8 are special operations, as there's nothing really changed. These operations are auditable because the complete set of actions is now useful for journalling. Action 7 and 8 are not necessarily useful to be used to produce entities with audit data to persist into the database, because it doesn’t necessarily have to be the case that the audited entity in question is saved/deleted later on, so the audit information is in that situation not persisted to the database as well, as the audit logic, the recorder, isn't asked for entities with audit data to persist in the same transaction as there is no transaction in progress. To be able to have reliable journalling, the information has to be logged by an external service. Also take into acount for action 7, it might be a lot of audit information is logged, as entity properties can be read a lot of times during the lifetime of an entity.
Note: |
| Authorizers and Validators often don't contain any state and therefore are usable as singletons. Auditors however record data and unless you're logging it right away, it's likely your auditor classes are collecting data during their lifetime which makes them stateful. This means that you shouldn't use them as singletons nor share them among entities but use a new instance every time you instantiate an Auditor. The LLBLGen Pro Dependency Injection mechanism is capable to perform that for you. |
Note: |
| Dependency Injection isn't available on the Compact Framework. To utilize Auditors on the compact framework, you're encouraged to create CreateAuditor overrides using include templates. |
// C#
/// <summary>Example Auditor class which is usable on all entities in a project.</summary>
[DependencyInjectionInfo(typeof(IEntity2), "AuditorToUse")]
[Serializable]
public class GeneralAuditor : AuditorBase
{
private enum AuditType
{
DeleteOfEntity=1,
DirectDeleteOfEntities,
DirectUpdateOfEntities,
DereferenceOfRelatedEntity,
ReferenceOfRelatedEntity,
EntityFieldSet,
InsertOfNewEntity,
UpdateOfExistingEntity
}
private List<AuditInfoEntity> _auditInfoEntities;
/// <summary>CTor </summary>
public GeneralAuditor()
{
_auditInfoEntities = new List<AuditInfoEntity>();
}
/// <summary>Audits the successful delete of an entity from the database</summary>
/// <param name="entity">The entity which was deleted.</param>
/// <remarks>As the entity passed in was deleted succesfully, reading values from the
/// passed in entity is only possible in this routine. After this call, the
/// state of the entity will be reset to Deleted again and reading the fields
/// will result in an exception. It's also recommended not to reference
/// the passed in entity in any audit entity you might want to persist as the entity
/// doesn't exist anymore in the database.</remarks>
public override void AuditDeleteOfEntity(IEntityCore entity)
{
AuditInfoEntity auditInfo = new AuditInfoEntity();
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName;
auditInfo.ActionDateTime = DateTime.Now;
auditInfo.ActionType = (int)AuditType.DeleteOfEntity;
_auditInfoEntities.Add(auditInfo);
}
/// <summary>Audits the successful dereference of related entity from the entity passed in.</summary>
/// <param name="entity">The entity of which the related entity was dereferenced from.</param>
/// <param name="relatedEntity">The related entity which was dereferenced from entity</param>
/// <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related
/// entity for which the related entity was dereferenced.</param>
public override void AuditDereferenceOfRelatedEntity(IEntityCore entity, IEntityCore relatedEntity,
string mappedFieldName)
{
AuditInfoEntity auditInfo = new AuditInfoEntity();
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName;
auditInfo.ActionDateTime = DateTime.Now;
auditInfo.ActionType = (int)AuditType.DereferenceOfRelatedEntity;
auditInfo.ActionData = string.Format("RelatedEntityName: {0}. MappedFieldName: {1}",
relatedEntity.LLBLGenProEntityName, mappedFieldName);
_auditInfoEntities.Add(auditInfo);
}
/// <summary>Audits the successful insert of a new entity into the database.</summary>
/// <param name="entity">The entity saved successfully into the database.</param>
public override void AuditInsertOfNewEntity(IEntityCore entity)
{
AuditInfoEntity auditInfo = new AuditInfoEntity();
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName;
auditInfo.ActionDateTime = DateTime.Now;
auditInfo.ActionType = (int)AuditType.InsertOfNewEntity;
_auditInfoEntities.Add(auditInfo);
}
/// <summary>
/// Audits the successful reference of related entity from the entity passed in.
/// </summary>
/// <param name="entity">The entity of which the related entity was dereferenced from.</param>
/// <param name="relatedEntity">The related entity which was dereferenced from entity</param>
/// <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related
/// entity for which the related entity was referenced.</param>
public override void AuditReferenceOfRelatedEntity(IEntityCore entity, IEntityCore relatedEntity,
string mappedFieldName)
{
AuditInfoEntity auditInfo = new AuditInfoEntity();
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName;
auditInfo.ActionDateTime = DateTime.Now;
auditInfo.ActionType = (int)AuditType.ReferenceOfRelatedEntity;
auditInfo.ActionData = string.Format("RelatedEntityName: {0}. MappedFieldName: {1}",
relatedEntity.LLBLGenProEntityName, mappedFieldName);
_auditInfoEntities.Add(auditInfo);
}
/// <summary>
/// Audits the successful update of an existing entity in the database
/// </summary>
/// <param name="entity">The entity updated successfully in the database.</param>
public override void AuditUpdateOfExistingEntity(IEntityCore entity)
{
AuditInfoEntity auditInfo = new AuditInfoEntity();
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName;
auditInfo.ActionDateTime = DateTime.Now;
auditInfo.ActionType = (int)AuditType.UpdateOfExistingEntity;
_auditInfoEntities.Add(auditInfo);
}
/// <summary>
/// Gets the audit entities to save. Audit entities contain the audit information stored
/// inside this auditor.
/// </summary>
/// <returns>The list of audit entities to save, or null if there are no audit entities to save</returns>
/// <remarks>Do not remove the audit entities and audit information from this auditor when this method is
/// called, as the transaction in which the save takes place can fail and retried which will result in
/// another call to this method</remarks>
public override IList GetAuditEntitiesToSave()
{
return _auditInfoEntities;
}
/// <summary>
/// The transaction with which the audit entities requested from GetAuditEntitiesToSave were saved.
/// Use this method to clear any audit data in this auditor as all audit information is persisted
/// successfully.
/// </summary>
public override void TransactionCommitted()
{
_auditInfoEntities.Clear();
}
}
' VB.NET
''' <summary>Example Auditor class which is usable on all entities in a project.</summary>
<DependencyInjectionInfo(GetType(IEntity2), "AuditorToUse"), _
Serializable()> _
Public Class GeneralAuditor
Inherits AuditorBase
Private Enum AuditType
DeleteOfEntity=1,
DirectDeleteOfEntities,
DirectUpdateOfEntities,
DereferenceOfRelatedEntity,
ReferenceOfRelatedEntity,
EntityFieldSet,
InsertOfNewEntity,
UpdateOfExistingEntity
End Enum
Private _auditInfoEntities As List(Of AuditInfoEntity)
''' <summary>CTor </summary>
Public Sub New()
_auditInfoEntities = New List(Of AuditInfoEntity)()
End Sub
''' <summary>Audits the successful delete of an entity from the database</summary>
''' <param name="entity">The entity which was deleted.</param>
''' <remarks>As the entity passed in was deleted succesfully, reading values from the
''' passed in entity is only possible in this routine. After this call, the
''' state of the entity will be reset to Deleted again and reading the fields
''' will result in an exception. It's also recommended not to reference
''' the passed in entity in any audit entity you might want to persist as the entity
''' doesn't exist anymore in the database.</remarks>
Public Overrides Sub AuditDeleteOfEntity(entity As IEntityCore)
Dim auditInfo As New AuditInfoEntity()
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName
auditInfo.ActionDateTime = DateTime.Now
auditInfo.ActionType = CInt(AuditType.DeleteOfEntity)
_auditInfoEntities.Add(auditInfo)
End Sub
''' <summary>Audits the successful dereference of related entity from the entity passed in.</summary>
''' <param name="entity">The entity of which the related entity was dereferenced from.</param>
''' <param name="relatedEntity">The related entity which was dereferenced from entity</param>
''' <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related
''' entity for which the related entity was dereferenced.</param>
Public Overrides Sub AuditDereferenceOfRelatedEntity(entity As IEntityCore, relatedEntity As IEntityCore, _
mappedFieldName As String)
Dim auditInfo As New AuditInfoEntity()
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName
auditInfo.ActionDateTime = DateTime.Now
auditInfo.ActionType = CInt(AuditType.DereferenceOfRelatedEntity)
auditInfo.ActionData = String.Format("RelatedEntityName: {0}. MappedFieldName: {1}", _
relatedEntity.LLBLGenProEntityName, mappedFieldName)
_auditInfoEntities.Add(auditInfo)
End Sub
''' <summary>Audits the successful insert of a new entity into the database.</summary>
''' <param name="entity">The entity saved successfully into the database.</param>
Public Overrides Sub AuditInsertOfNewEntity(entity As IEntityCore)
Dim auditInfo As New AuditInfoEntity()
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName
auditInfo.ActionDateTime = DateTime.Now
auditInfo.ActionType = CInt(AuditType.InsertOfNewEntity)
_auditInfoEntities.Add(auditInfo)
End Sub
''' <summary>
''' Audits the successful reference of related entity from the entity passed in.
''' </summary>
''' <param name="entity">The entity of which the related entity was dereferenced from.</param>
''' <param name="relatedEntity">The related entity which was dereferenced from entity</param>
''' <param name="mappedFieldName">Name of the mapped field onto the relation from entity to related
''' entity for which the related entity was referenced.</param>
Public Overrides Sub AuditReferenceOfRelatedEntity(entity As IEntityCore, relatedEntity As IEntityCore,
mappedFieldName As String)
Dim auditInfo As New AuditInfoEntity()
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName
auditInfo.ActionDateTime = DateTime.Now
auditInfo.ActionType = CInt(AuditType.ReferenceOfRelatedEntity)
auditInfo.ActionData = string.Format("RelatedEntityName: {0}. MappedFieldName: {1}", _
relatedEntity.LLBLGenProEntityName, mappedFieldName)
_auditInfoEntities.Add(auditInfo)
End Sub
''' <summary>
''' Audits the successful update of an existing entity in the database
''' </summary>
''' <param name="entity">The entity updated successfully in the database.</param>
Public Overrides Sub AuditUpdateOfExistingEntity(entity As IEntityCore)
Dim auditInfo As New AuditInfoEntity()
auditInfo.AffectedEntityName = entity.LLBLGenProEntityName
auditInfo.ActionDateTime = DateTime.Now
auditInfo.ActionType = CInt(AuditType.UpdateOfExistingEntity)
_auditInfoEntities.Add(auditInfo)
End Sub
''' <summary>
''' Gets the audit entities to save. Audit entities contain the audit information stored
''' inside this auditor.
''' </summary>
''' <returns>The list of audit entities to save, or null if there are no audit entities to save</returns>
''' <remarks>Do not remove the audit entities and audit information from this auditor when this method is
''' called, as the transaction in which the save takes place can fail and retried which will result in
''' another call to this method</remarks>
Public Overrides Function GetAuditEntitiesToSave() As IList
Return _auditInfoEntities
End Function
''' <summary>
''' The transaction with which the audit entities requested from GetAuditEntitiesToSave were saved.
''' Use this method to clear any audit data in this auditor as all audit information is persisted
''' successfully.
''' </summary>
Public Overrides Sub TransactionCommitted()
_auditInfoEntities.Clear()
End Sub
End Class